/*
 * Copyright (C)
 * Licensed under the Apache License, Version 2.0 (the "License");
 */

#include "securec.h"
#include "sle_device_discovery.h"
#include "sle_connection_manager.h"
#include "sle_ssap_client.h"
#include "SLE_LED_Client.h"
#include "soc_osal.h"
#include "app_init.h"
#include "common_def.h"

#include "debug_print.h"
#include "pinctrl.h"
#include "gpio.h"
#include "ssd1306.h"
#include "ssd1306_fonts.h"

#define SLE_MTU_SIZE_DEFAULT 300
#define SLE_SEEK_INTERVAL_DEFAULT 100
#define SLE_SEEK_WINDOW_DEFAULT 100
#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16

static sle_announce_seek_callbacks_t g_seek_cbk = {0};
static sle_connection_callbacks_t g_connect_cbk = {0};
static ssapc_callbacks_t g_ssapc_cbk = {0};
static sle_addr_t g_remote_addr = {0};
static uint16_t g_conn_id = 0;
static ssapc_find_service_result_t g_find_service_result = {0};

/* OLED显示结构体 */
static SSD1306_t g_ssd1306 = {0};

/**
 * @brief 初始化OLED
 */
static void oled_init(void)
{
    ssd1306_Init();
    ssd1306_Fill(Black);
    ssd1306_UpdateScreen();
    ssd1306_SetCursor(0, 0);
    ssd1306_DrawString("Temp: ", Font_6x8, White);
    ssd1306_DrawString("Humidity: ", Font_6x8, White);
    ssd1306_UpdateScreen();
}

/**
 * @brief 更新OLED显示
 */
static void oled_update_display(float temperature, float humidity)
{
    char temp_str[16];
    char humidity_str[16];

    sprintf(temp_str, "Temp: %.2f C", temperature);
    sprintf(humidity_str, "Humidity: %.2f %%", humidity);

    ssd1306_SetCursor(0, 8);
    ssd1306_Fill(Black);
    ssd1306_DrawString(temp_str, Font_6x8, White);
    ssd1306_DrawString(humidity_str, Font_6x8, White);
    ssd1306_UpdateScreen();
}

/**
 * @brief 处理接收到的通知数据（温度和湿度）
 */
static void handle_notify_data(const uint8_t *data, uint8_t len)
{
    if (len != 8) {
        PRINT("[SLE Client] Invalid notify data length\r\n");
        return;
    }

    float temperature = 0.0;
    float humidity = 0.0;

    memcpy(&temperature, data, sizeof(float));
    memcpy(&humidity, data + 4, sizeof(float));

    PRINT("[SLE Client] Received Temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity);

    /* 更新OLED显示 */
    oled_update_display(temperature, humidity);
}

/**
 * @brief 处理服务器发送的通知
 */
static void example_sle_server_notification_cbk(uint8_t client_id,
                                               uint16_t conn_id,
                                               ssapc_handle_value_t *data,
                                               errcode_t status)
{
    PRINT("[SLE Client] Notification cbk client_id:0x%x, conn_id:0x%x, status:0x%x\r\n",
          client_id, conn_id, status);

    if (status != ERRCODE_SUCC) {
        PRINT("[SLE Client] Notification status not success\r\n");
        return;
    }

    /* 根据handle区分是温度还是湿度 */
    if (data->handle == g_temp_handle || data->handle == g_humidity_handle) {
        handle_notify_data(data->data, data->data_len);
    }
}

/**
 * @brief 处理读取请求
 */
static void example_sle_client_read_request_cbk(uint8_t client_id,
                                                uint16_t conn_id,
                                                ssaps_req_read_cb_t *read_cb_para,
                                                errcode_t status)
{
    PRINT("[SLE Client] Read request cbk client_id:0x%x, conn_id:0x%x, handle:0x%x, status:0x%x\r\n",
          client_id, conn_id, read_cb_para->handle, status);
}

/**
 * @brief 处理写请求（LED控制）
 */
static void example_sle_client_write_request_cbk(uint8_t client_id,
                                                 uint16_t conn_id,
                                                 ssaps_req_write_cb_t *write_cb_para,
                                                 errcode_t status)
{
    PRINT("[SLE Client] Write request cbk client_id:0x%x, conn_id:0x%x, handle:0x%x, status:0x%x\r\n",
          client_id, conn_id, write_cb_para->handle, status);

    if (status != ERRCODE_SUCC) {
        PRINT("[SLE Client] Write status not success\r\n");
        return;
    }

    /* 解析LED控制指令 */
    if (write_cb_para->length == 7 &&
        write_cb_para->value[0] == 'R' && write_cb_para->value[1] == 'L' &&
        write_cb_para->value[2] == 'E' && write_cb_para->value[3] == 'D' &&
        write_cb_para->value[4] == '_' && write_cb_para->value[5] == 'O' &&
        write_cb_para->value[6] == 'N') {
        /* 红灯打开 */
        uapi_gpio_set_val(GPIO_07, GPIO_LEVEL_HIGH);
        PRINT("[SLE Client] Red LED ON\r\n");
    } else if (write_cb_para->length == 8 &&
               write_cb_para->value[0] == 'R' && write_cb_para->value[1] == 'L' &&
               write_cb_para->value[2] == 'E' && write_cb_para->value[3] == 'D' &&
               write_cb_para->value[4] == '_' && write_cb_para->value[5] == 'O' &&
               write_cb_para->value[6] == 'F' && write_cb_para->value[7] == 'F') {
        /* 红灯关闭 */
        uapi_gpio_set_val(GPIO_07, GPIO_LEVEL_LOW);
        PRINT("[SLE Client] Red LED OFF\r\n");
    }
    /* 处理其他颜色的LED控制指令（黄灯、绿灯）同理 */
}

/**
 * @brief 注册SSAPS回调函数
 */
static errcode_t example_sle_ssaps_register_cbks(void)
{
    ssaps_callbacks_t ssaps_cbk = {0};
    ssaps_cbk.start_service_cb = NULL; // 客户端不需要
    ssaps_cbk.mtu_changed_cb = NULL;   // 可选
    ssaps_cbk.read_request_cb = example_sle_client_read_request_cbk;
    ssaps_cbk.write_request_cb = example_sle_client_write_request_cbk;
    ssaps_cbk.notification_cb = example_sle_server_notification_cbk;
    ssaps_cbk.indication_cb = NULL; // 可选
    return ssaps_register_callbacks(&ssaps_cbk);
}

/**
 * @brief 订阅服务端的温度和湿度特性
 */
static errcode_t subscribe_to_temp_humidity(void)
{
    /* 假设服务端的温度和湿度特性已经添加，并且g_temp_handle和g_humidity_handle已经获取 */

    /* 订阅温度特性通知 */
    ssaps_subscription_t temp_sub = {0};
    temp_sub.handle = g_temp_handle;
    temp_sub.enable = true;
    if (ssaps_subscribe(g_server_id, g_conn_id, &temp_sub) != ERRCODE_SUCC) {
        PRINT("[SLE Client] Subscribe temperature fail\r\n");
        return ERRCODE_FAIL;
    }

    /* 订阅湿度特性通知 */
    ssaps_subscription_t humidity_sub = {0};
    humidity_sub.handle = g_humidity_handle;
    humidity_sub.enable = true;
    if (ssaps_subscribe(g_server_id, g_conn_id, &humidity_sub) != ERRCODE_SUCC) {
        PRINT("[SLE Client] Subscribe humidity fail\r\n");
        return ERRCODE_FAIL;
    }

    PRINT("[SLE Client] Subscribed to temperature and humidity notifications\r\n");
    return ERRCODE_SUCC;
}

/**
 * @brief 初始化SLE客户端
 */
static errcode_t initialize_sle_client(void)
{
    errcode_t ret = ERRCODE_FAIL;

    /* 使能SLE */
    ret = enable_sle();
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Client] Enable SLE fail\r\n");
        return ERRCODE_FAIL;
    }

    /* 注册回调函数 */
    ret = example_sle_ssaps_register_cbks();
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Client] Register SSAPS callbacks fail\r\n");
        return ERRCODE_FAIL;
    }

    /* 添加服务并获取特性句柄 */
    ret = example_sle_server_add();
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Client] Add server fail\r\n");
        return ERRCODE_FAIL;
    }

    /* 连接到服务端 */
    sle_addr_t addr = {0};
    memcpy_s(addr.addr, SLE_ADDR_LEN, g_sle_local_addr, SLE_ADDR_LEN);
    ret = sle_connect_remote_device(&addr);
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Client] Connect to remote device fail\r\n");
        return ERRCODE_FAIL;
    }

    return ERRCODE_SUCC;
}

/**
 * @brief 主任务
 */
static int example_sle_led_client_task(const char *arg)
{
    unused(arg);

    /* 初始化OLED */
    oled_init();

    osal_msleep(5000); /* 延时5s，等待SLE初始化完毕 */

    PRINT("[SLE Client] Try to initialize SLE client\r\n");
    if (initialize_sle_client() != ERRCODE_SUCC) {
        PRINT("[SLE Client] Initialize SLE client fail!\r\n");
        return -1;
    }

    /* 等待连接建立并订阅通知 */
    osal_msleep(2000);
    if (subscribe_to_temp_humidity() != ERRCODE_SUCC) {
        PRINT("[SLE Client] Subscribe to notifications fail!\r\n");
        return -1;
    }

    PRINT("[SLE Client] SLE client initialized and subscribed\r\n");

    return 0;
}

#define SLE_LED_CLI_TASK_PRIO 24
#define SLE_LED_CLI_STACK_SIZE 0x2000

static void example_sle_led_client_entry(void)
{
    osal_task *task_handle = NULL;

    osal_kthread_lock();
    task_handle = osal_kthread_create((osal_kthread_handler)example_sle_led_client_task, NULL, "SLELedClientTask",
                                      SLE_LED_CLI_STACK_SIZE);
    if (task_handle != NULL) {
        osal_kthread_set_priority(task_handle, SLE_LED_CLI_TASK_PRIO);
        osal_kfree(task_handle);
    }
    osal_kthread_unlock();
}

/* 运行客户端入口 */
app_run(example_sle_led_client_entry);
